package cn.hfjava.kz.common.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;

/**
 * 公用数据分析监听器
 * @author: lds
 */
@Slf4j
public class PublicReadExcelListener<M extends BaseMapper<T>,T> implements ReadListener<T> {

    private final static int BATCH_NUM = 1000;

    private final int batchNum;

    List<T> data = new ArrayList<>();

    private final ServiceImpl<M,T> service;
    private Function<T,Boolean>[] conditions = null;

    public PublicReadExcelListener(ServiceImpl<M,T> service){
        this(service,BATCH_NUM);
    }
    public PublicReadExcelListener(ServiceImpl<M,T> service,int batchNum){
        this.service = service;
        this.batchNum = batchNum;
    }

    @SafeVarargs
    public PublicReadExcelListener(ServiceImpl<M,T> service, Function<T,Boolean>... conditions){
        this(service,BATCH_NUM);
        this.conditions = conditions;
    }

    @SafeVarargs
    public PublicReadExcelListener(ServiceImpl<M,T> service, int batchNum,Function<T,Boolean>... conditions){
        this(service,batchNum);
        this.conditions = conditions;
    }

    @Override
    public void invoke(T t, AnalysisContext analysisContext) {
        //解析数据，添加到集合中
        Boolean conform = Objects.nonNull(conditions) ?  this.moreConditions(t,conditions) : Boolean.TRUE;
        if (conform) {
            data.add(t);
        }
        if (data.size() >= batchNum){
            service.saveBatch(data,batchNum);
            data.clear();
        }
    }

    /**
     * 每解析完一页sheet页就会调用该方法
     * @param analysisContext 分析上下文
     */
    @SneakyThrows
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        log.info("读取当前文件第【"+(analysisContext.readSheetHolder().getSheetNo() + 1)+"】sheet页");
        if (data.size() > 0){
            service.saveBatch(data,batchNum);
        }
        data = new ArrayList<>();
    }

    /**
     * 多条件过滤
     * @param t 实体
     * @param conditions 条件
     * @return 返回当前数据是否符合条件
     */
    @SafeVarargs
    private final Boolean moreConditions(T t, Function<T, Boolean>... conditions){
        Boolean conform = Boolean.TRUE;
        for (Function<T, Boolean> func : conditions) {
            conform = func.apply(t) && conform;
        }
        return conform;
    }
}
